package com.superdp.service.impl;

import com.superdp.dto.Result;
import com.superdp.entity.SeckillVoucher;
import com.superdp.entity.VoucherOrder;
import com.superdp.mapper.VoucherOrderMapper;
import com.superdp.service.ISeckillVoucherService;
import com.superdp.service.IVoucherOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.superdp.utils.RedisIdWorker;
import com.superdp.utils.SimpleRedisLock;
import com.superdp.utils.UserHolder;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 */
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {

    @Resource
    private ISeckillVoucherService seckillVoucherService;

    @Resource
    private RedisIdWorker redisIdWorker;

    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Resource
    RedissonClient redissonClient;
    /**
     * 优惠劵秒杀
     * @param voucherId
     */
    @Override
    public Result secskillVoucher(Long voucherId) {
        //1.查询秒杀是否开始
        SeckillVoucher seckillVoucher = seckillVoucherService.getById(voucherId);
        LocalDateTime beginTime = seckillVoucher.getBeginTime();
        LocalDateTime endTime = seckillVoucher.getEndTime();
        LocalDateTime now = LocalDateTime.now();
        if(now.isBefore(beginTime)){
            return Result.fail("秒杀未开始!");
        }
        if(now.isAfter(endTime)){
            return Result.fail("秒杀已结束！");
        }
        //2.查询库存是否充足
        Integer stock = seckillVoucher.getStock();
        if(stock<=0){
            return Result.fail("优惠劵已抢光！");
        }

        Long userId = UserHolder.getUser().getId();
        //集群环境下获取分布式锁
     //  SimpleRedisLock lock = new SimpleRedisLock("order:" + userId, stringRedisTemplate);
        //改用redisson分布式锁
        RLock lock = redissonClient.getLock("lock:order:" + userId);

        boolean b = lock.tryLock();
        if(!b){
            System.out.println("不允许重复下单！");
        }
        try {
            IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();
            return  proxy.createVoucherOrder(voucherId);
        }finally {
            lock.unlock();
        }
    }

    @Transactional
    public Result createVoucherOrder(Long voucherId) {
        //3.一人一单
        //3.1查询是否已经创建了订单
        Long userId=UserHolder.getUser().getId();
        Integer count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();
        if(count>0){
            return Result.fail("用户已经下过单了！");
        }

        //3.扣减库存
        //乐观锁解决超卖sql：update tb_seckill_voucher set stock=stock-1 where voucher_id=${} and stock>0;
        boolean success = seckillVoucherService.update().setSql("stock=stock-1")
                .eq("voucher_id", voucherId).gt("stock",0).update();
        if(!success){
            return Result.fail("库存不足！");
        }

        //4.生成订单
        long orderId = redisIdWorker.nextId("order");
        VoucherOrder voucherOrder = new VoucherOrder();
        voucherOrder.setId(orderId);
        voucherOrder.setUserId(UserHolder.getUser().getId());
        voucherOrder.setVoucherId(voucherId);
        save(voucherOrder);

        return Result.ok(orderId);
    }
}
